#include <stdio.h>
#include <vector>
#include <algorithm>
using namespace std;

struct Edge
{
	int src;
	int des;
	int cost;
	bool operator<(const Edge& rhs) const
	{
		return cost < rhs.cost;
	}
};

vector<Edge> edges;

static const int V = 100;
int parent[V];

void init(int n)
{
	edges.clear();
	for (int i = 0; i < n; ++i)
		parent[i] = -1;
}

int root(int &v)
{
	int depth = 0;
	while (parent[v] != -1)
	{
		v = parent[v];
		++depth;
	}
	return depth;
}

bool merge(int& a, int& b)
{
	int d1 = root(a);
	int d2 = root(b);
	if (a == b)
		return false;

	if (d1 < d2)
		parent[a] = b;
	else
		parent[b] = a;

	return true;
}

int Kruskal(int n)
{
	sort (edges.begin(), edges.end());
	int amount = 0;
	for (vector<Edge>::iterator it = edges.begin(); it != edges.end(); ++it)
	{
		if (merge(it->src, it->des))
		{
			amount += it->cost;
			if (--n == 1)
				return amount;
		}
	}
	return -1;
}

int main()
{
	while (1)
	{
		int n, m;
		scanf ("%d %d", &n, &m);
		if (n == 0)
			break;

		init (m);
		while (n--)
		{
			Edge edge;
			scanf ("%d %d %d", &edge.src, &edge.des, &edge.cost);
			--edge.des, --edge.src;
			edges.push_back(edge);
		}

		int amount = Kruskal(m);
		if (amount == -1)
			printf ("?\n");
		else
			printf ("%d\n", amount);
	}
	return 0;
}